﻿using Cloud.Core.Model.Payments;
using Essensoft.AspNetCore.Payment.WeChatPay.V2.Notify;
using Essensoft.AspNetCore.Payment.WeChatPay;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System.Threading.Tasks;
using System;

using Essensoft.AspNetCore.Payment.WeChatPay.V2;
using Cloud.Core.Options;
using SKIT.FlurlHttpClient.Wechat.TenpayV3.Models;
using log4net.Repository.Hierarchy;
using SKIT.FlurlHttpClient.Wechat.TenpayV3;
using Cloud.Core.Request.WebChat.WxUser;
using System.IO;
using System.Text;
using SKIT.FlurlHttpClient.Wechat.TenpayV3.Settings;
using Microsoft.AspNetCore.Hosting;
using SKIT.FlurlHttpClient.Wechat.TenpayV3.Utilities;
using System.Security.Cryptography;
using System.Collections.Generic;
using static SKIT.FlurlHttpClient.Wechat.TenpayV3.Models.QueryMarketingPayGiftActivityMerchantsResponse.Types;

namespace Cloud.Core.Controllers.WebChat
{
    /// <summary>
    /// 微信支付API控制器，用于处理微信支付相关的通知和请求。
    /// </summary>
    [ApiController]
    [Route("api/wx/pay")]
   
    public class PayApiController : ControllerBase
    {

        private readonly ILogger _logger;
        private readonly WechatTenpayClientOptions _tenpayOptions;
        private readonly Services.HttpClients.IWechatTenpayClientFactory _wechatTenpayClientFactory;


        public IWebHostEnvironment Environment { get; }

        public  PayApiController(

       ILogger<PayApiController> logger,
          IOptions<Options.TenpayOptions> tenpayOptions,
          Services.HttpClients.IWechatTenpayClientFactory wechatTenpayClientFactory, IWebHostEnvironment env)
        {
            _logger = logger;
           // _tenpayOptions = tenpayOptions.Value;
            _wechatTenpayClientFactory = wechatTenpayClientFactory;
            var manager = new InMemoryCertificateManager();
            Environment = env;
             _tenpayOptions = new WechatTenpayClientOptions()
            {
                 //MerchantId = "1629382165",
                 //MerchantV3Secret = "2a0b76b4065bcc29e2a3f8e7b2bd5228",
                 //MerchantCertificateSerialNumber = "12EB01D90D6C01CAA280CC037D9D7AD9EE6296AD",
                 //MerchantCertificatePrivateKey = System.IO.File.ReadAllText(Environment.ContentRootPath+ "/PayWeChatCert/wechatpay_12EB01D90D6C01CAA280CC037D9D7AD9EE6296AD.pem"),
                 //PlatformCertificateManager = manager
                 MerchantId = "1629382165",
                 MerchantV3Secret = "2a0b76b4065bcc29e2a3f8e7b2bd5228",
                 MerchantCertificateSerialNumber = "70DAE606A6E6C10B8E56B477F8C3DD989F094CF4",
                 MerchantCertificatePrivateKey = System.IO.File.ReadAllText(Environment.ContentRootPath + "/PayWeChatCert/apiclient_key.pem"),
                 PlatformCertificateManager = manager

             };
        }


    


        [HttpPost]
        [Route("jsapi")]
        public async Task<IActionResult> CreateOrderByJsapi([FromBody] CreateOrderByJsapiRequest requestModel)
        {
            var client = _wechatTenpayClientFactory.Create(requestModel.MerchantId);
            var request = new CreatePayTransactionJsapiRequest()
            {
                OutTradeNumber = "SAMPLE_OTN_" + DateTimeOffset.Now.ToString("yyyyMMddHHmmssfff"),
                AppId = requestModel.AppId,
                Description = "演示订单",
                NotifyUrl = "https://example.com",
                Amount = new CreatePayTransactionJsapiRequest.Types.Amount() { Total = requestModel.Amount },
                Payer = new CreatePayTransactionJsapiRequest.Types.Payer() { OpenId = requestModel.OpenId }
            };
            var response = await client.ExecuteCreatePayTransactionJsapiAsync(request, cancellationToken: HttpContext.RequestAborted);
             if (!response.IsSuccessful())
            {
                _logger.LogWarning(
                    "JSAPI 下单失败（状态码：{0}，错误代码：{1}，错误描述：{2}）。",
                    response.GetRawStatus(), response.ErrorCode, response.ErrorMessage
                );
            }

            return new JsonResult(response);
        }

        [HttpPost]
        [Route("miniprogram")]
        public async Task<IActionResult> CreateOrderByMiniProgram([FromBody] CreateOrderByMiniProgramRequest requestModel)
        {
            try
            {
                // 配置WechatTenpayClient选项
                var options = new WechatTenpayClientOptions
                {
                    MerchantId = "1629382165", // 商户号
                    MerchantV3Secret = "2a0b76b4065bcc29e2a3f8e7b2bd5228", // API v3密钥
                    MerchantCertificateSerialNumber = "538E07FD3CD8D894AED43E9E43E42F72D048564C",
                    MerchantCertificatePrivateKey = System.IO.File.ReadAllText(Environment.ContentRootPath + "/PayWeChatCert/apiclient_key.pem"),
                    // PlatformCertificateManager = manager
                };
                var client = new WechatTenpayClient(options);
                var request = new CreatePayTransactionJsapiRequest()
                {
                    OutTradeNumber = $"MP_{DateTimeOffset.Now.ToString("yyyyMMddHHmmssfff")}",
                    AppId = requestModel.AppId,
                    Description = requestModel.Description,
                    NotifyUrl = requestModel.NotifyUrl,
                    Amount = new CreatePayTransactionJsapiRequest.Types.Amount() 
                    { 
                        Total = requestModel.Amount,
                        Currency = "CNY"
                    },
                    Payer = new CreatePayTransactionJsapiRequest.Types.Payer() 
                    { 
                        OpenId = requestModel.OpenId 
                    }
                };

                var response = await client.ExecuteCreatePayTransactionJsapiAsync(request, 
                    cancellationToken: HttpContext.RequestAborted);

                if (!response.IsSuccessful())
                {
                    _logger.LogWarning(
                        "小程序支付下单失败（状态码：{0}，错误代码：{1}，错误描述：{2}）。",
                        response.GetRawStatus(), response.ErrorCode, response.ErrorMessage
                    );
                    return BadRequest(new { code = -1, msg = response.ErrorMessage });
                }

                // 生成随机字符串
                string nonceStr = Guid.NewGuid().ToString("N");
                string timestamp = DateTimeOffset.Now.ToUnixTimeSeconds().ToString();

                // 构建签名字符串（按照微信支付小程序 API v3 的规则）
               // string message = $"{requestModel.AppId}\n{timestamp}\n{nonceStr}\nprepay_id={response.PrepayId}\n";

                // 使用 client 实例生成签名
              //  string paySign = client.GenerateSignature(message);
                string appId = requestModel.AppId; // 小程序 AppId
                //long timeStamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); // 时间戳
                //string nonceStr = Guid.NewGuid().ToString("N").Substring(0, 16); // 随机字符串
                string paySignKey = "2a0b76b4065bcc29e2a3f8e7b2bd5228"; // 商户 API v3 密钥

                // 生成签名
                string signature = GenerateWechatMiniProgramPaySignature(
                    response.PrepayId,
                    appId,
                    timestamp,
                    nonceStr,
                    paySignKey
                );
                // 返回小程序调起支付所需参数
                var payParams = new
                {
                    timeStamp = timestamp,
                    nonceStr = nonceStr,
                    package = $"prepay_id={response.PrepayId}",
                    signType = "RSA2048",
                    paySign = signature
                };
                List<IDictionary<string, string>> keyValuePairs = new List<IDictionary<string, string>>();
                var paramMap = client.GenerateParametersForJsapiPayRequest(request.AppId, response.PrepayId);
                keyValuePairs.Add(paramMap);
                
                
                IDictionary<string, string> orderdic = new Dictionary<string, string> { { "orderid", request.OutTradeNumber } };
                
                keyValuePairs.Add(orderdic);

                return Ok(new { status = 0, data = keyValuePairs,msg="支付成功" });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "小程序支付下单异常");
                return BadRequest(new { code = -1, msg = "支付下单失败" });
            }
        }
        /// <summary>
        /// 生成微信小程序支付签名
        /// </summary>
        /// <param name="prepayId">预支付交易会话标识</param>
        /// <param name="appId">小程序 AppId</param>
        /// <param name="timeStamp">时间戳</param>
        /// <param name="nonceStr">随机字符串</param>
        /// <param name="paySignKey">商户密钥（API v3 密钥）</param>
        /// <returns>支付签名</returns>
        public static string GenerateWechatMiniProgramPaySignature (
            string prepayId,
            string appId,
            string timeStamp,
            string nonceStr,
            string paySignKey )
        {
            // 构造待签名字符串
            StringBuilder sb = new StringBuilder();
            sb.Append("prepay_id=").Append(prepayId)
              .Append("&")
              .Append("timestamp=").Append(timeStamp)
              .Append("&")
              .Append("nonce_str=").Append(nonceStr)
              .Append("&")
              .Append("package=signType=RSA2048")
              .Append("&")
              .Append("app_id=").Append(appId);

            // 添加商户 API v3 密钥
            sb.Append("&").Append(paySignKey);

            // 计算签名（HMAC-SHA256）
            using (var hmacsha256 = new HMACSHA256(Encoding.UTF8.GetBytes(paySignKey)))
            {
                byte[] hashMessage = hmacsha256.ComputeHash(Encoding.UTF8.GetBytes(sb.ToString()));
                return BitConverter.ToString(hashMessage).Replace("-", "").ToUpper();
            }
        }
        [HttpPost]
        [Route("m-{merchant_id}/message-push")]
        public async Task<IActionResult> ReceiveMessage(
              [FromRoute(Name = "merchant_id")] string merchantId,
              [FromHeader(Name = "Wechatpay-Timestamp")] string timestamp,
              [FromHeader(Name = "Wechatpay-Nonce")] string nonce,
              [FromHeader(Name = "Wechatpay-Signature")] string signature,
              [FromHeader(Name = "Wechatpay-Serial")] string serialNumber)
        {
            using var reader = new StreamReader(Request.Body, Encoding.UTF8);
            string content = await reader.ReadToEndAsync();
            _logger.LogInformation("接收到微信支付推送的数据：{0}", content);

            var client = _wechatTenpayClientFactory.Create(merchantId);
            bool valid = client.VerifyEventSignature(
                webhookTimestamp: timestamp,
                webhookNonce: nonce,
                webhookBody: content,
                webhookSignature: signature,
                webhookSerialNumber: serialNumber
            );
            if (!valid)
            {
                // NOTICE:
                //   需提前注入 CertificateManager、并下载平台证书，才可以使用扩展方法执行验签操作。
                //   请参考本示例项目 TenpayCertificateRefreshingBackgroundService 后台任务中的相关实现。
                //   有关 CertificateManager 的完整介绍请参阅《开发文档 / 基础用法 / 如何验证回调通知事件签名？》。
                //   后续如何解密并反序列化，请参阅《开发文档 / 基础用法 / 如何解密回调通知事件中的敏感数据？》。

                return new JsonResult(new { code = "FAIL", message = "验签失败" });
            }

            var callbackModel = client.DeserializeEvent(content);
            var eventType = callbackModel.EventType?.ToUpper();
            switch (eventType)
            {
                case "TRANSACTION.SUCCESS":
                    {
                        var callbackResource = client.DecryptEventResource<SKIT.FlurlHttpClient.Wechat.TenpayV3.Events.TransactionResource>(callbackModel);
                        _logger.LogInformation("接收到微信支付推送的订单支付成功通知，商户订单号：{0}", callbackResource.OutTradeNumber);
                        // 后续处理略
                    }
                    break;

                default:
                    {
                        // 其他情况略
                    }
                    break;
            }

            return new JsonResult(new { code = "SUCCESS", message = "成功" });
        }

        [HttpPost]
        [Route("transfer")]
        public async Task<IActionResult> TransferToUser([FromBody] TransferToUserRequest requestModel)
        {
            try
            {
               // var client = _wechatTenpayClientFactory.Create("1629382165");
                // 配置微信支付相关参数
                string mchId = "1629382165"; // 商户号
                string serialNo = "538E07FD3CD8D894AED43E9E43E42F72D048564C"; // API 证书序列号
                string privateKeyPath = System.IO.File.ReadAllText(Environment.ContentRootPath + "/PayWeChatCert/apiclient_key.pem"); // API 证书私钥（通常为 `apiclient_key.pem` 文件内容）。
                string privateKeyPassword = "2a0b76b4065bcc29e2a3f8e7b2bd5228"; // API v3 密钥

                // 初始化 WeChatTenpayClient
                var client = new WechatTenpayClient(new WechatTenpayClientOptions
                {
                    MerchantId = mchId,
                    MerchantCertificateSerialNumber = serialNo,
                    MerchantCertificatePrivateKey = privateKeyPath,
                    MerchantV3Secret = privateKeyPassword
                });
                // 创建商家转账到零钱请求
                var request = new CreateTransferBatchRequest()
                {
                    AppId = "wx80a16c6d4b037812",
                    OutBatchNumber = $"TF{DateTimeOffset.Now.ToString("yyyyMMddHHmmssfff")}",
                    BatchName = "奖励提现",
                    BatchRemark = "答题奖励提现",
                    TotalAmount = requestModel.Amount,
                    TotalNumber = 1,
                    TransferDetailList = new List<CreateTransferBatchRequest.Types.TransferDetail>()
                    {
                        new CreateTransferBatchRequest.Types.TransferDetail()
                        {
                            OutDetailNumber = $"TD{DateTimeOffset.Now.ToString("yyyyMMddHHmmssfff")}",
                            TransferAmount = requestModel.Amount,
                            TransferRemark = "答题奖励发放",
                            OpenId = requestModel.OpenId
                           // UserName = requestModel.UserName
                        }
                    }
                };

                var response = await client.ExecuteCreateTransferBatchAsync(request, 
                    cancellationToken: HttpContext.RequestAborted);

                if (!response.IsSuccessful())
                {
                    _logger.LogWarning(
                        "用户提现失败（状态码：{0}，错误代码：{1}，错误描述：{2}）。",
                        response.GetRawStatus(), response.ErrorCode, response.ErrorMessage
                    );
                    return BadRequest(new { code = -1, msg = response.ErrorMessage });
                }

                return Ok(new { 
                    code = 0, 
                    data = new {
                        batchId = response.BatchId,
                        outBatchNo = request.OutBatchNumber
                    },
                    msg = "提现申请成功"
                });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "用户提现处理异常");
                return BadRequest(new { code = -1, msg = "提现处理失败" });
            }
        }
    }
}
